// HSS.Forms.MainModuleContainer.cs
// ----------------------------------------------------------------------------
// Licensed under the MIT license
// http://www.opensource.org/licenses/mit-license.html
// ----------------------------------------------------------------------------
// HighSpeed-Solutions, LLC
// Copyright (c) 2001-2010
// ----------------------------------------------------------------------------
// File:       MainModuleContainer.cs
// Author:     HSS\gbanta
// Created:    08/12/2010
// Modified:   12/23/2010
// ----------------------------------------------------------------------------
namespace HSS.Forms
{
	#region Using Directives
	using System;
	using System.Collections.Specialized;
	using System.ComponentModel;
	using System.Drawing;
	using System.Windows.Forms;


	#endregion

	#region MainModuleContainer
	/// <summary>
	/// Summary description for MainModuleContainer.
	/// </summary>
	public partial class MainModuleContainer : Form
	{
		static object lockObject = new object();

		/// <summary>
		/// Default Constructor
		/// </summary>
		public MainModuleContainer()
		{
			//
			// Required for Windows Form Designer support
			//
			InitializeComponent();
		}

		#region Child Module Handlers

		/// <summary>
		/// The dynamically added Module
		/// </summary>
		public HSS.Forms.MainModuleBase ChildModule
		{
			get { return _childModule; }
			set { _childModule = value; }
		} HSS.Forms.MainModuleBase _childModule;

		/// <summary>
		/// Initializes the dynamically added Module
		/// </summary>
		/// <param name="objModule">The Module to add</param>
		/// <param name="KeyName">The name to associate with the Module</param>
		public void InitializeModuleContainer(MainModuleBase objModule, string KeyName)
		{
			if (null != objModule)
			{
				_childModule = objModule;
				_childModule.Name = KeyName;
				_childModule.Visible = true;
				_childModule.Dock = DockStyle.Fill;

				// Child Module's Parent Form Icon
				if (null != _childModule.ParentIcon)
					this.Icon = _childModule.ParentIcon;

				// Child Module - Image
				if (null != _childModule.Image)
					this.pbxModuleIcon.Image = _childModule.Image;

				// ShowInTaskbar
				this.ShowInTaskbar = _childModule.ShowInTaskbar;

				// Maximize
				this.MaximizeBox = _childModule.MaximizeBox;

				// Minimize
				this.MinimizeBox = _childModule.MinimizeBox;

				// FormBorderStyle
				this.FormBorderStyle = _childModule.ParentBorderStyle;

				// StartPosition
				this.StartPosition = _childModule.ParentStartPosition;

				// Size
				this.MinimumSize = this._childModule.MinimumSize;
				this.MaximumSize = this._childModule.MaximumSize;

				this._childModule.MinimumSize = new Size();
				this._childModule.MaximumSize = new Size();

				this.ResizeParent();

				this.pnlDetail.Controls.Add(_childModule);

			}
			else
				throw new ArgumentNullException("objModule", "The Find Module object [" + KeyName + "] is not instantiated or is null");
		}


		/// <summary>
		/// InitializeModule
		/// </summary>
		/// <param name="Data">An array of IDataContainer Objects to list</param>
		/// <param name="HeaderText">The text to display in the header</param>
		public bool InitializeModule(HSS.Data.IDataContainer[] Data, string HeaderText)
		{

			this.Text = HeaderText;

			if (!_childModule.InitializeModule(Data))
				return false;

			// Header Visible
			if (_childModule.HeaderVisible)
			{
				this.pnlHeader.Height = _childModule.HeaderHeight;

				// Module Title
				if (!string.IsNullOrEmpty(_childModule.ModuleTitle))
					this.lblModuleTitle.Text = _childModule.ModuleTitle;
				else
					this.lblModuleTitle.Text = HeaderText;

				// Action Description
				if (!string.IsNullOrEmpty(_childModule.ActionDescription))
					this.lblActionDescription.Text = _childModule.ActionDescription;
				else
					this.lblActionDescription.Text = Application.ProductName;
			}
			else
			{
				this.pnlHeader.Height = 0;
			}

			return true;
		}


		/// <summary>
		/// Force a resize of the Parent Form (this)
		/// </summary>
		public void ResizeParent()
		{
			ResizeParent(_childModule.Size);
		}


		/// <summary>
		/// Force a resize of the Parent Form (this)
		/// </summary>
		/// <param name="NewSize">The minimum size for the Child Module</param>
		public void ResizeParent(Size NewSize)
		{
			if (this.WindowState == FormWindowState.Normal)
			{
				int newHeight =
						(this._childModule.HeaderVisible ? this._childModule.HeaderHeight : 0) +
						NewSize.Height;

				int newWidth = NewSize.Width;

				this.ClientSize = new Size(newWidth, newHeight);
			}
		}


		/// <summary>
		/// Indicates if this instance is the Active Instance
		/// </summary>
		public bool IsActive
		{
			get { return _isActive; }
			set { _isActive = value; }
		} bool _isActive = false;

		#endregion

		#region Properties
		/// <summary>
		/// The Title or Overview for the child Module
		/// </summary>
		[Description("The Title or Overview for the child Module")]
		[Category("Display")]
		public string ModuleTitle
		{
			get { return this.lblModuleTitle.Text; }
			set { this.lblModuleTitle.Text = value; }
		}
		/// <summary>
		/// The description or action for this child Module
		/// </summary>
		[Description("The description or action for this child Module")]
		[Category("Display")]
		public string ActionDescription
		{
			get { return this.lblActionDescription.Text; }
			set { this.lblActionDescription.Text = value; }
		}
		#endregion

		#region Events Handlers
		private void MainModuleContainer_Activated(object sender, EventArgs e)
		{
			//this.pnlFooter.Active = true;
			this._isActive = true;
		}
		private void MainModuleContainer_Deactivate(object sender, EventArgs e)
		{
			this._isActive = false;
			//this.pnlFooter.Active = false;
		}
		private void MainModuleContainer_FormClosing(object sender, FormClosingEventArgs e)
		{
			if (!e.Cancel)
				CloseInstance(this);
		}
		#endregion

		#region Static Helpers
		/// <summary>
		/// The number of open Configuration Editor forms
		/// </summary>
		public static int InstanceCount
		{
			get { return _instanceCount; }
			private set { _instanceCount = value; }
		} static int _instanceCount;
		/// <summary>
		/// Array of Configuration Editor Form Instances
		/// </summary>
		public static MainModuleContainer[] Instances()
		{
			MainModuleContainer[] local = new MainModuleContainer[_instances.Count];
			_instances.Values.CopyTo(local, 0);
			return local;
		} static HybridDictionary _instances = new HybridDictionary(false);
		/// <summary>
		/// Returns the active instance
		/// </summary>
		public static MainModuleContainer ActiveInstance
		{
			get
			{
				MainModuleContainer[] local = new MainModuleContainer[_instances.Count];
				_instances.Values.CopyTo(local, 0);
				foreach (MainModuleContainer instance in local)
				{
					if (instance._isActive)
					{
						return instance;
					}
				}
				return null;
			}
		}
		/// <summary>
		/// Returns the active instance specified by the name
		/// </summary>
		/// <param name="Name">The name of the Child Module</param>
		public static MainModuleContainer GetInstance(string Name)
		{
			MainModuleContainer[] local = new MainModuleContainer[_instances.Count];
			_instances.Values.CopyTo(local, 0);
			foreach (MainModuleContainer instance in local)
			{
				if (instance._childModule.Name == Name)
				{
					return instance;
				}
			}
			return null;
		}
		/// <summary>
		/// Load the Config Form
		/// </summary>
		/// <param name="ModuleTypeName">The TypeName of the Main Module to load in the Container</param>
		/// <param name="FormTitle">The Title to display</param>
		/// <param name="Data">An array of IDataContainer Object to list</param>
		/// <param name="HeaderVisible">Show the Header Section of the Form</param>
		/// <param name="ShowAsDialog">Indicates if the instance should be shown as a Modal Dialog</param>
		/// <param name="owner">The Owning Parent Form</param>
		public static DialogResult LoadInstance(string ModuleTypeName, string FormTitle, HSS.Data.IDataContainer[] Data, bool HeaderVisible, bool ShowAsDialog, IWin32Window owner)
		{
			// Must have a valid Type to continue
			if (string.IsNullOrEmpty(ModuleTypeName))
				throw new ArgumentNullException("ModuleTypeName", "ModuleTypeName [ " + ModuleTypeName + " ] cannot be empty or null.");

			// The Type to create
			Type t = Type.GetType(ModuleTypeName, false);

			// Must have a valid Type to continue
			if (null == t)
				throw new InvalidCastException("Requested Module Type [ " + ModuleTypeName + " ] does not exist or is not available.");

			return LoadInstance(t, FormTitle, Data, HeaderVisible, ShowAsDialog, owner);
		}
		/// <summary>
		/// Load the Config Form
		/// </summary>
		/// <param name="ModuleType">The Type of the Main Module to load in the Container</param>
		/// <param name="FormTitle">The Title to display</param>
		/// <param name="Data">An array of IDataContainer Object to list</param>
		/// <param name="HeaderVisible">Show the Header Section of the Form</param>
		/// <param name="ShowAsDialog">Indicates if the instance should be shown as a Modal Dialog</param>
		/// <param name="owner">The Owning Parent Form</param>
		public static DialogResult LoadInstance(Type ModuleType, string FormTitle, HSS.Data.IDataContainer[] Data, bool HeaderVisible, bool ShowAsDialog, IWin32Window owner)
		{
			// Must have a valid Type to continue
			if (null == ModuleType)
				throw new ArgumentNullException("ModuleType", "ModuleType cannot be null.");

			HSS.Forms.MainModuleBase _childModule = null;
			DialogResult result = DialogResult.None;
			MainModuleContainer _detailForm = null;
			try
			{
				_detailForm = new MainModuleContainer();
				_detailForm.Name = "MainModuleContainer" + _detailForm.GetHashCode().ToString("x");
				_detailForm.IsActive = true;
				_detailForm.pnlHeader.Visible = HeaderVisible;
				_instances.Add(_detailForm.Name, _detailForm);
				System.Threading.Interlocked.Increment(ref _instanceCount);

				// Cast from MainModuleBase to the Instance Type Requested.
				string moduleTypeName = ModuleType.FullName;
				_childModule = ModuleType.Assembly.CreateInstance(moduleTypeName) as HSS.Forms.MainModuleBase;

				// Initialize the Container
				_detailForm.InitializeModuleContainer(_childModule, moduleTypeName + _instanceCount.ToString());

				// Initialize the Module
				if (_detailForm.InitializeModule(Data, FormTitle))
				{
					if (ShowAsDialog)
					{
						result = _detailForm.ShowDialog(owner);
						if (null != _detailForm)
							_detailForm.Dispose(true);
					}
					else
					{
						_detailForm.Show(owner);
						_detailForm.BringToFront();
					}
				}
				else
				{
					CloseInstance(_detailForm);
					if (null != _detailForm)
						_detailForm.Dispose(true);
				}
			}
			catch (Exception ex)
			{
				CloseInstance(_detailForm);
				if (null != _detailForm)
				{
					_detailForm.Dispose(true);
				}
				MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
			}
			return result;
		}
		/// <summary>
		/// Run this container as the Main Form for an Application
		/// </summary>
		/// <param name="ModuleTypeName">The TypeName of the Main Module to load in the Container</param>
		/// <param name="FormTitle">The Forms Title text</param>
		/// <param name="Data">Any data to pass into the Main Module</param>
		/// <param name="HeaderVisible">Show the Header Section of the Form</param>
		public static void ApplicationRun(string ModuleTypeName, string FormTitle, HSS.Data.IDataContainer[] Data, bool HeaderVisible)
		{
			ApplicationRun(ModuleTypeName, FormTitle, Data, HeaderVisible, false);
		}
		/// <summary>
		/// Run this container as the Main Form for an Application
		/// </summary>
		/// <param name="ModuleType">The Type of the Main Module to load in the Container</param>
		/// <param name="FormTitle">The Forms Title text</param>
		/// <param name="Data">Any data to pass into the Main Module</param>
		/// <param name="HeaderVisible">Show the Header Section of the Form</param>
		public static void ApplicationRun(Type ModuleType, string FormTitle, HSS.Data.IDataContainer[] Data, bool HeaderVisible)
		{
			ApplicationRun(ModuleType, FormTitle, Data, HeaderVisible, false);
		}
		/// <summary>
		/// Run this container as the Main Form for an Application
		/// </summary>
		/// <param name="ModuleTypeName">The TypeName of the Main Module to load in the Container</param>
		/// <param name="FormTitle">The Forms Title text</param>
		/// <param name="Data">Any data to pass into the Main Module</param>
		/// <param name="HeaderVisible">Show the Header Section of the Form</param>
		/// <param name="UseModuleMenu">Use the Menu of the Module, not the Container</param>
		public static void ApplicationRun(string ModuleTypeName, string FormTitle, HSS.Data.IDataContainer[] Data, bool HeaderVisible, bool UseModuleMenu)
		{
			// Must have a valid Type to continue
			if (string.IsNullOrEmpty(ModuleTypeName))
				throw new ArgumentNullException("ModuleTypeName", "ModuleTypeName [ " + ModuleTypeName + " ] cannot be empty or null.");

			// The Type to create
			Type t = Type.GetType(ModuleTypeName, false);

			// Must have a valid Type to continue
			if (null == t)
				throw new InvalidCastException("Requested Module Type [ " + ModuleTypeName + " ] does not exist or is not available.");

			ApplicationRun(t, FormTitle, Data, HeaderVisible, UseModuleMenu);
		}
		/// <summary>
		/// Run this container as the Main Form for an Application
		/// </summary>
		/// <param name="ModuleType">The Type of the Main Module to load in the Container</param>
		/// <param name="FormTitle">The Forms Title text</param>
		/// <param name="Data">Any data to pass into the Main Module</param>
		/// <param name="HeaderVisible">Show the Header Section of the Form</param>
		/// <param name="UseModuleMenu">Use the Menu of the Module, not the Container</param>
		public static void ApplicationRun(Type ModuleType, string FormTitle, HSS.Data.IDataContainer[] Data, bool HeaderVisible, bool UseModuleMenu)
		{
			// Must have a valid Type to continue
			if (null == ModuleType)
				throw new ArgumentNullException("ModuleType", "ModuleType cannot be null.");

			using (MainModuleContainer _detailForm = new MainModuleContainer())
			{
				_detailForm.Name = "MainModuleContainer" + _detailForm.GetHashCode().ToString("x");
				_detailForm.IsActive = true;
				_detailForm.pnlHeader.Visible = HeaderVisible;

				// Cast from MainModuleBase to the Instance Type Requested.
				string moduleTypeName = ModuleType.FullName;
				HSS.Forms.MainModuleBase _childModule = ModuleType.Assembly.CreateInstance(moduleTypeName) as HSS.Forms.MainModuleBase;
				_childModule.IsMainForm = true;

				// Initialize the Container
				_detailForm.InitializeModuleContainer(_childModule, moduleTypeName + "_main");

				// Initialize the Module
				if (_detailForm.InitializeModule(Data, FormTitle))
				{
					// Main Message Loop
					if (UseModuleMenu && null != _childModule.MenuSystem)
						_detailForm.MainMenuStrip = _childModule.MenuSystem;
					Application.Run(_detailForm);
				}
			}
		}
		/// <summary>
		/// Closes a MainModuleContainer instance
		/// </summary>
		/// <param name="instance">A MainModuleContainer instance</param>
		private static void CloseInstance(MainModuleContainer instance)
		{
			if (null != instance)
			{
				try
				{
				}
				finally
				{
					try
					{
						string name = instance.Name;
						if (MainModuleContainer._instances.Contains(name))
						{
							MainModuleContainer._instances.Remove(name);
							System.Threading.Interlocked.Decrement(ref _instanceCount);
						}
					}
					catch { }
				}
			}
		}
		#endregion

	}
	#endregion
}